import java.util.Arrays;

public class Sort {
    public static void main1(String[] args) {
        int[] arr = {5,3,7,4,8,2,1};
        InsertSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 直接插入排序
     *
     * 时间复杂度：
     *    最坏情况下：O(n^2)  5 4 3 2 1
     *    最好情况下：O(n)    1 2 3 4 5
     * 空间复杂度：O(1)
     * 应用场景： 当数据趋于有序的情况下 直接插入排序效率会变高
     * @param arr
     */
    public static void InsertSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            int tmp = arr[i];
            int j = i - 1;
            for (; j >= 0 ; j--) {
                if(arr[j] > tmp) {
                    arr[j+1] = arr[j];
                }else {
                    //arr[j+1] = tmp;
                    break;
                }
            }
            //走到这 j 的值为 -1；
            arr[j+1] = tmp;//最前面的值也大于 tmp，tmp要插入到 j+1 位置
        }
    }



    public static void func(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            int tmp = arr[i];
            int j = i-1;
            for (; j >= 0; j--) {
                if(arr[j] > tmp) {
                    arr[j+1] = arr[j];
                }else {
                    break;
                }
            }
            arr[j+1] = tmp;
        }
    }


    /**
     * 希尔排序
     */

    public static void shellSort(int[] arr) {
        int gap = arr.length;
        //gap为组数
        while((gap/=2) >= 1) {
            shell(arr,gap);
        }
    }
public static void shell(int[] arr,int gap) {
    for (int i = gap; i < arr.length; i++) {
        int tmp = arr[i];
        int j = i-gap;
        for (; j >= 0; j -= gap) {
            if(arr[j] > tmp) {
                arr[j+gap] = arr[j];
            }else {
                break;
            }
        }
        arr[j+gap] = tmp;
    }
}



    /**
     * 选择排序
     * 时间复杂度：O(n^2)
     * 空间复杂度：O(1)
     * 稳定性：不稳定
     */
    public static void selectSort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            int minIndex = i;
            for (int j = i+1; j < arr.length; j++) {
                if(arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            swap(arr,i,minIndex);
        }
    }
    private static void swap(int[] arr,int i,int minIndex) {
        int tmp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = tmp;
    }

    public static void main3(String[] args) {
        int[] arr = {5,3,2,4,1};
        selectSort(arr);
        System.out.println(Arrays.toString(arr));
    }


    /**
     * 选择排序 2
     *
     */
    public static void Sort2(int[] arr) {
        int left = 0;
        int right = arr.length - 1;
        while(left < right) {
            int minIndex = left;
            int maxIndex = left;
            for (int i = left+1; i <= right; i++) {
                if(arr[i] < arr[minIndex]) {
                    minIndex = i;
                }
                if(arr[i] > arr[maxIndex]) {
                    maxIndex = i;
                }
            }
            swap(arr,left,minIndex);
            //防止第一个元素为 最大值
            //如果第一个元素是最大值，那么上条语句交换后，最大值就会被交换到 minIndex 下标位置
            //所以 此时 maxIndex 就需要维护 到 minIndex 下标位置
            if(maxIndex == left) {
                maxIndex = minIndex;
            }
            swap(arr,right,maxIndex);
            left++;
            right--;
        }
    }

    public static void main4(String[] args) {
        int[] arr = {5,1,4,3,2,6};
        Sort2(arr);
        System.out.println(Arrays.toString(arr));
    }


    /**
     * 堆排序
     */
    public static void heapSort(int arr[]) {
        createHeap(arr);
        for (int end = arr.length-1; end > 0; end--) {
            swap(arr,0,end);
            shiftDown(arr,0,end);
        }
    }

    public static void main(String[] args) {
        int[] arr = {5,1,4,3,2,6};
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    private static void createHeap(int[] arr) {
        for (int parent = (arr.length-1-1)/2; parent >= 0 ; parent--) {
            shiftDown(arr,parent,arr.length);
        }
    }
    private static void shiftDown(int[] arr,int parent,int len) {
        int child = 2 * parent + 1;

        while(child < len) {
            //找孩子结点中的较大的一个
            if(child+1 < len && arr[child] < arr[child+1]) {
                child++;
            }
            if(arr[parent] < arr[child]) {
                swap(arr,parent,child);
                parent = child;
                child = 2 * parent + 1;
            }else {
                break;
            }
        }
    }





}
